var Ctj = Ctj||{};
Ctj.apply = function(){
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;
	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		// Skip the boolean and the target
		target = arguments[ i ] || {};
		i++;
	}
	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !Ctj.isFunction(target) ) {
		target = {};
	}
	// Extend Lhb itself if only one argument is passed
	if ( i === length ) {
		target = this;
		i--;
	}
	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];
				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}
				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( Ctj.isPlainObject(copy) || (copyIsArray = Ctj.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && Ctj.isArray(src) ? src : [];
					} else {
						clone = src && Ctj.isPlainObject(src) ? src : {};
					}
					// Never move original objects, clone them
					target[ name ] = Ctj.apply( deep, clone, copy );
				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}
	// Return the modified object
	return target;
}
/**
 * 
 */
Ctj.apply(Ctj,{
	emptyFn:function(){},
	ns:function(){
		var len1 = arguments.length,
        i = 0,
        len2,
        j,
        main,
        ns,
        sub,
        current;
        
	    for(; i < len1; ++i) {
	        main = arguments[i];
	        ns = arguments[i].split('.');
	        current = window[ns[0]];
	        if (current === undefined) {
	            current = window[ns[0]] = {};
	        }
	        sub = ns.slice(1);
	        len2 = sub.length;
	        for(j = 0; j < len2; ++j) {
	            current = current[sub[j]] = current[sub[j]] || {};
	        }
	    }
	    return current;
	},
	encode : function(obj) {
		return JSON.stringify(obj);
	},
	decode : function(ss) {
		return eval("(" + ss + ")");
	},
	getId:function(prefix){
		prefix = prefix||"Lhb";
		return prefix+"_" + ((Math.random(0)+"").substring(2));
	},
	createMgr : function(mgrType) {
		var mgr = {};
		mgr[mgrType + "Map"] = {};
		mgr[mgrType + "List"] = [];
		mgr["get" + mgrType + "Info"] = function(typeCode) {
			return mgr[mgrType + "Map"][typeCode];
		}
		mgr["add" + mgrType] = function(typeCode, typeInfo) {
			mgr[mgrType + "Map"][typeCode] = typeInfo;
			return this;
		};
		mgr["regist" + mgrType] = mgr["add" + mgrType];
		mgr["remove" + mgrType] = function(typeCode) {
			delete mgr[mgrType + "Map"][typeCode];
			return this;
		}
		return mgr;
	},
	uuid : function() {
		var s = [];
		var hexDigits = "0123456789abcdef";
		for ( var i = 0; i < 36; i++) {
			s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
		}
		s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
		s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the
		s[8] = s[13] = s[18] = s[23] = "-";
		var uuid = s.join("");
		return uuid;
	},
	each:function(array, fn, scope){
        if(!Ctj.isArray(array)&&!Ctj.isArguments(array)){
        	array = [array];
        }
        for(var i = 0, len = array.length; i < len; i++){
            if(fn.call(scope || array[i], array[i], i, array) === false){
                return i;
            };
        }
    },
    getTopWin:function(){
		if(!Ctj.topWin){
			Ctj.topWin= window;
			while(Ctj.topWin.top != null && Ctj.topWin.top.location != Ctj.topWin.location) {
				Ctj.topWin = Ctj.topWin.top;
			}
		}
		return Ctj.topWin;
	}
});

/**
 * �ж�����
 */
Ctj.apply(Ctj,{
	isString : function(v) {
		return typeof v === "string";
	},
	isArguments : function(arg) {
		return Object.prototype.toString.call(arg) === "[object Arguments]"||arg.callee||arg.caller;
	},
	isObject : function(o) {
		return typeof o === "object";
	},
	isEmptyObj : function(o) {
		if (!o) {
			return true;
		}
		var is = true;
		for ( var name in o) {
			is = false;
		}
		return is;
	},
	isEmpty : function(v, allowBlank){
         return v === null || v === undefined || ((Ctj.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
    },
	isArray : function(a) {
		return Object.prototype.toString.call(a) === "[object Array]";
	},
	isFunction : function(f) {
		return typeof f === "function";
	},
	isDate : function(d) {
		return Object.prototype.toString.call(d) === "[object Date]";
	},
	isNumber : function(n) {
		return typeof n === "number";
	},
	isRealNumber : function(n){
		return Ctj.isNumber(n)&&!isNaN(n)
	},
	isPrimitive:function(v){
		return Ctj.isString(v) || Ctj.isNumber(v) || Ctj.isBoolean(v);
	},
	isPlainObject:function(obj){
		// Not plain objects:
		// - Any object or value whose internal [[Class]] property is not "[object Object]"
		// - DOM nodes
		// - window
		if ( jQuery.type( obj ) !== "object" ||obj===null|| obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}
		if ( obj.constructor &&!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
			return false;
		}
		// If the function hasn't returned already, we're confident that
		// |obj| is a plain object, created by {} or constructed with new Object
		return true;
	},
	isElement: function(value) {
        return value ? value.nodeType === 1 : false;
    }
});
/**
 * 浏览器类型
 */
(function() {
	var ua = navigator.userAgent.toLowerCase();
	var check = function(r) {
		return r.test(ua);
	};
	var DOC = document, docMode = DOC.documentMode;

	Ctj.isOpera = check(/opera/);
	Ctj.isChrome = check(/\bchrome\b/);
	Ctj.isWebKit = check(/webkit/);
	Ctj.isSafari = !Ctj.isChrome && check(/safari/);
	Ctj.isSafari2 = Ctj.isSafari && check(/applewebkit\/4/); // unique to Safari
	// 2
	Ctj.isSafari3 = Ctj.isSafari && check(/version\/3/);
	Ctj.isSafari4 = Ctj.isSafari && check(/version\/4/);
	Ctj.isIE11 = check(/rv:11/) && check(/trident/);
	Ctj.isIE = (!Ctj.isOpera && check(/msie/)) || Ctj.isIE11;
	Ctj.isIE7 = Ctj.isIE && (check(/msie 7/) || docMode == 7);
	Ctj.isIE8 = Ctj.isIE && (check(/msie 8/) && docMode != 7);
	Ctj.isIE9 = Ctj.isIE && check(/msie 9/);
	Ctj.isIE10 = Ctj.isIE && check(/msie 10/);
	Ctj.isIE6 = Ctj.isIE && !Ctj.isIE7 && !Ctj.isIE8 && !Ctj.isIE9 && !Ctj.isIE10
			&& !Ctj.isIE11;
	Ctj.isGecko = !Ctj.isWebKit && check(/gecko/);
	Ctj.isGecko2 = Ctj.isGecko && check(/rv:1\.8/);
	Ctj.isGecko3 = Ctj.isGecko && check(/rv:1\.9/);

	Ctj.isWindows = check(/windows|win32/);
	Ctj.isMac = check(/macintosh|mac os x/);
	Ctj.isAir = check(/adobeair/);
	Ctj.isLinux = check(/linux/);
})();(function($){
	var _ajax = $.ajax;
	$.ajax = function(url,options){
		if ( typeof url === "object" ) {
			options = url;
		}else{
			options = options || {};
			options.url = url;
		}
		//当url地址栏以 “/”开头是自动添加 地址前缀
		if($.ajax.basePath){
			if(options.url.indexOf("/")==0){
				options.url = $.ajax.basePath+options.url;
			}
		}
		
		options = $.extend({
			type : "get",
			showMask:true,
			waitMsg:null,
			successMsg:null,
			errorMsg:null
		},options);
		
		var dealOptions={
			success : function(data, textStatus) {
				if(options._progress){
					Ctj.closeProgress(options._progress);
				}
				if (typeof options.success === "function") {
					return options.success.apply(this,arguments);
				} else {
					if(!options.complete){
						Ctj.alert(options.successMsg|| "调用成功");
					}
				}
			},
			// 加载等待中
			beforeSend : function() {
				if (typeof options.beforeSend === "function") {
					if(options.beforeSend.apply(this,arguments)===false){
						return false;
					}
				}
				if(options.showMask&&(options.waitMsg||$.ajax.waitMsg)){
					options._progress= Ctj.showProgress({
						title:"提示",
						msg:options.waitMsg||$.ajax.waitMsg,
						interval:500
					});
				}
			},
			error : function(XMLHttpRequest, textStatus,errorThrown) {
				if(options._progress){
					Ctj.closeProgress(options._progress);
				}
				if (typeof options.error === "function") {
					return options.error.apply(this,arguments);
				}else{
					var error = $.ajax.parseError(XMLHttpRequest, textStatus,errorThrown);
					Ctj.error(error);
				}
			}
			
		}
		return _ajax($.extend({},options,dealOptions));
	};
	
	$.ajax.basePath=null;
	$.ajax.waitMsg=null;
	$.ajax.parseError=function(XMLHttpRequest, textStatus,errorThrown){
		var error="";
		if (XMLHttpRequest.status == "404") {
			error = "404 不存在当前请求地址：";
		} else if(XMLHttpRequest.status == "417"||XMLHttpRequest.status == "500"){
			error = XMLHttpRequest.responseText ? (XMLHttpRequest.responseText.substring(0, 300)):"程序异常";
		} else {
			var s = "请求失败，错误代码"+XMLHttpRequest.status+"。"
			error = XMLHttpRequest.responseText ? (s+XMLHttpRequest.responseText.substring(0, 300)):s+"请稍后重试...";
		}
		return error;
	}
})(jQuery);
Ctj.Cookie={
	set:function(name,value,time){
      var cookieString=name+'='+encodeURIComponent(value); 
      //判断是否设置过期时间默认是小时
      if(time>0){ 
         var date=new Date(); 
         date.setTime(date.getTime+time*3600*1000); 
         cookieString=cookieString+'; expires='+date.toGMTString(); 
      } 
      document.cookie=cookieString;
     
   },
   get:function(name){
      var strCookie=document.cookie;
      var arrCookie=strCookie.split('; '); 
      for(var i=0;i<arrCookie.length;i++){ 
         var arr=arrCookie[i].split('='); 
         if(arr[0]==name)return decodeURIComponent(arr[1]); 
      } 
      return null; 
   },
   "delete":function(name){
      var date=new Date(); 
      date.setTime(date.getTime()-10000); 
      document.cookie=name+'=v; expires='+date.toGMTString(); 
   }	
};
Ctj.setCookie=function(){
	Ctj.Cookie.set.apply(this,arguments);
};
Ctj.getCookie=function(){
	return Ctj.Cookie.get.apply(this,arguments);
};
Ctj.delCookie=function(){
	Ctj.Cookie["delete"].apply(this,arguments);
};


/**
 * 封装jQuery扩展方法
 */
(function($){
	$.define=function(cname,config){
		/**
		 * cname:类名称
		 * config={
		 * 		create:function($t,state){},
		 * 		autoRender:null/true/false/0,1,2,
		 * 		extend:"",
		 * 		getState:function(){},
		 * 		get$t:function(){},
		 * 
		 * 		method:function(){}
		 * 		getMethod:function(){},
		 * }
		 * config:function(){}
		 */
		if(!cname||!config){
			return;
		}
		if(typeof config==="function"){
			return $.fn[cname] = config;
		}
		
		var fn = $.fn[cname]=function(options,param){
			if (typeof options == 'string') {
				var methodName = options;
				var args =Array.prototype.slice.call(arguments,1);
				if(methodName.startsWith("get")){
					if(this.length==0){
						return null;
					}
					var $t = this.length==1?this:$(this[0]);
					var state = $t.data(cname);
					var method = state.options[methodName];
					if(typeof method==="function"){
						return method.apply(state.options,args);
					}
				}else{
					return this.each(function(){
						var state = $.data(this, cname);
						var method = state.options[methodName];
						if(typeof method==="function"){
							method.apply(state.options,args);
						}
					});
				}
				return;
			}
			options = options || {};
			return this.each(function() {				
				var state = $.data(this, cname);
				if (state) {
					$.extend(true,state.options, options);
				} else {
					state = $.data(this, cname, {
						options : $.extend(true,{}, fn.prototype,$.parser.parseOptions(this),fn.prototype.parseOptions(this),options)
					});
				}
				state.options.getState = function(){
					return state;
				}
				var $t = $(this);
				state.options.get$t= function(){
					return $t;
				}
				state.options.create.call(state.options,$t,state);
			});
		};
		
		
		var pname = config.extend;
		fn.$methodName="create";
		fn.$owner = fn;
		if(pname&&$.fn[pname]){
			var pFn = $.fn[pname];
			var tempF = function(){};
			tempF.prototype = pFn.prototype;
			
			fn.superclass=pFn.prototype;
			fn.prototype = $.extend({
				create:function(){},
				parseOptions:function(){},
				superclass:pFn,
				callParent:function(arg){
					var caller = arguments.callee.caller;
					var $methodName = caller.$methodName;
					var $owner = caller.$owner;
					var superMethod = $owner.superclass[$methodName];
					if (superMethod) {
						var arg2 = arg;
						if (!arg) {
							arg2 = arguments;
						} else {
							if (!Ctj.isArguments(arg) && !Ctj.isArray(arg)) {
								arg2 = arguments;
							}
						}
						if(Ctj.isArguments(arg2)){
							arg2 = Array.prototype.slice.call(arg2);
						}
						return superMethod.apply(this, arg2);
					} else {
						throw new Error("Parent no such method :" + $methodName);
					}
				}
			},new tempF());
			Ctj.override(fn,config);
		}else{
			fn.prototype = {
				create:function(){},
				parseOptions:function(){}
			};		
			Ctj.override(fn,config);
		}	
		
		//增加到jQuery.parse中
		if($.parser&&(Ctj.isNumber(config.autoRender)||config.autoRender)){
			config.parseName = cname;
			if(Ctj.isNumber(config.autoRender)){
				$.parser.plugins = [config.parseName].concat($.parser.plugins);
			}else{
				$.parser.plugins.push(config.parseName);
			}
		}
		return fn;
	};
})(jQuery);
/**
 * 覆盖
 */
Ctj.override = function(origclass, overrides) {
	if (overrides) {
		var p = origclass.prototype;
		for ( var name in overrides) {
			p[name] = overrides[name];
			if (typeof p[name] === "function") {
				p[name].$methodName = name;
				p[name].$owner = origclass;
			}
		}
		if (Ctj.isIE && overrides.hasOwnProperty('toString')) {
			p.toString = overrides.toString;
		}
	}
};
/**
 * 继承
 */
Ctj.extend = (function() {
	var io = function(o) {
		for ( var m in o) {
			this[m] = o[m];
		}
	};
	var oc = Object.prototype.constructor;
	return function(sb, sp, overrides) {
		if (typeof sp == 'object') {
			overrides = sp;
			sp = sb;
			sb = overrides.constructor != oc ? overrides.constructor
					: function() {
						sp.apply(this, arguments);
					};
		}
		var F = function() {
		}, sbp, spp = sp.prototype;

		F.prototype = spp;
		sbp = sb.prototype = new F();
		sbp.constructor = sb;
		sb.$methodName = "constructor";
		sb.$owner = sb;
		sb.superclass = spp;
		if (spp.constructor == oc) {
			spp.constructor = sp;
		}
		sb.override = function(o) {
			Ctj.override(sb, o);
		};
		sbp.superclass = sbp.supr = (function() {
			return spp;
		});
		sbp.override = io;
		sbp.callParent = function(arg) {
			var caller = arguments.callee.caller;
			var $methodName = caller.$methodName;
			var $owner = caller.$owner;
			var superMethod = $owner.superclass[$methodName];
			if (superMethod) {
				var arg2 = arg;
				if (!arg) {
					arg2 = arguments;
				} else {
					if (!Ctj.isArguments(arg) && !Ctj.isArray(arg)) {
						arg2 = arguments;
					}
				}
				if(Ctj.isArguments(arg2)){
					arg2 = Array.prototype.slice.call(arg2);
				}
				return superMethod.apply(this, arg2);
			} else {
				throw new Error("Parent no such method :" + $methodName);
			}
		};
		Ctj.override(sb, overrides);
		sb.extend = function(o) {
			return Ctj.extend(sb, o);
		};
		return sb;
	};
})();
/**
 * 定义类
 */
Ctj.define = function(cname,option){
	Ctj.ns(cname);
	var sb = eval(cname),pname =option.extend;
	var sp = pname?eval(pname):Ctj.Base;
	sb = Ctj.extend(sp,option);
	return sb;
};Ctj.Format = function() {
    var trimRe         = /^\s+|\s+$/g,
    stripTagsRE    = /<\/?[^>]+>/gi,
    stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
    nl2brRe        = /\r?\n/g;

	return {
	    /**
	     * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
	     * @param {String} value The string to truncate
	     * @param {Number} length The maximum length to allow before truncating
	     * @param {Boolean} word True to try to find a common work break
	     * @return {String} The converted text
	     */
	    ellipsis : function(value, len, word) {
	        if (value && value.length > len) {
	            if (word) {
	                var vs    = value.substr(0, len - 2),
	                    index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
	                if (index == -1 || index < (len - 15)) {
	                    return value.substr(0, len - 3) + "...";
	                } else {
	                    return vs.substr(0, index) + "...";
	                }
	            } else {
	                return value.substr(0, len - 3) + "...";
	            }
	        }
	        return value;
	    },
	
	    /**
	     * Checks a reference and converts it to empty string if it is undefined
	     * @param {Mixed} value Reference to check
	     * @return {Mixed} Empty string if converted, otherwise the original value
	     */
	    undef : function(value) {
	        return value !== undefined ? value : "";
	    },
	    /**
	     * Checks a reference and converts it to the default value if it's empty
	     */
	    defaultValue : function(value, defaultValue) {
	        return value !== undefined && value !== '' ? value : defaultValue;
	    },
	
	    /**
	     * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
	     */
	    htmlEncode : function(value) {
	        return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
	    },
	    /**
	     * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
	     */
	    htmlDecode : function(value) {
	        return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
	    },
	    /**
	     * Trims any whitespace from either side of a string
	     */
	    trim : function(value) {
	        return String(value).replace(trimRe, "");
	    },
	    /**
	     * Returns a substring from within an original string
	     */
	    substr : function(value, start, length) {
	        return String(value).substr(start, length);
	    },
	    /**
	     * Converts a string to all lower case letters
	     */
	    lowercase : function(value) {
	        return String(value).toLowerCase();
	    },
	    /**
	     * Converts a string to all upper case letters
	     */
	    uppercase : function(value) {
	        return String(value).toUpperCase();
	    },
	
	    /**
	     * Converts the first character only of a string to upper case
	     * @param {String} value The text to convert
	     * @return {String} The converted text
	     */
	    capitalize : function(value) {
	        return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
	    },
	
	    // private
	    call : function(value, fn) {
	        if (arguments.length > 2) {
	            var args = Array.prototype.slice.call(arguments, 2);
	            args.unshift(value);
	            return eval(fn).apply(window, args);
	        } else {
	            return eval(fn).call(window, value);
	        }
	    },
	
	    /**
	     * Format a number as US currency
	     * @param {Number/String} value The numeric value to format
	     * @return {String} The formatted currency string
	     */
	    usMoney : function(v) {
	        v = (Math.round((v-0)*100))/100;
	        v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
	        v = String(v);
	        var ps = v.split('.'),
	            whole = ps[0],
	            sub = ps[1] ? '.'+ ps[1] : '.00',
	            r = /(\d+)(\d{3})/;
	        while (r.test(whole)) {
	            whole = whole.replace(r, '$1' + ',' + '$2');
	        }
	        v = whole + sub;
	        if (v.charAt(0) == '-') {
	            return '-$' + v.substr(1);
	        }
	        return "$" +  v;
	    },
	
	    /**
	     * Parse a value into a formatted date using the specified format pattern.
	     * @param {String/Date} value The value to format (Strings must conform to the format expected by the javascript Date object's <a href="http://www.w3schools.com/jsref/jsref_parse.asp">parse()</a> method)
	     * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
	     * @return {String} The formatted date string
	     */
	    date : function(d, fmt) {
	    	if (!fmt) {
	    		if (!d) {
	    			d = new Date();
	    			fmt = 'yyyy-MM-dd';
	    		} else {
	    			if (Ctj.isDate(d)) {
	    				fmt = 'yyyy-MM-dd';
	    			} else {
	    				fmt = d;
	    				d = new Date();
	    			}
	    		}
	    	}
	    	var o = {
	    		"M+" : d.getMonth() + 1, // �·�
	    		"d+" : d.getDate(), // ��
	    		"h+" : d.getHours(), // Сʱ
	    		"m+" : d.getMinutes(), // ��
	    		"s+" : d.getSeconds(), // ��
	    		"q+" : Math.floor((d.getMonth() + 3) / 3), // ����
	    		"S" : d.getMilliseconds()
	    	// ����
	    	};
	    	if (/(y+)/.test(fmt))
	    		fmt = fmt.replace(RegExp.$1, (d.getFullYear() + "")
	    				.substr(4 - RegExp.$1.length));
	    	for ( var k in o)
	    		if (new RegExp("(" + k + ")").test(fmt))
	    			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k])
	    					: (("00" + o[k]).substr(("" + o[k]).length)));
	    	return fmt;
	    },
	
	    /**
	     * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
	     * @param {String} format Any valid date format string
	     * @return {Function} The date formatting function
	     */
	    dateRenderer : function(format) {
	        return function(v) {
	            return Ctj.Format.date(v, format);
	        };
	    },
	
	    /**
	     * Strips all HTML tags
	     * @param {Mixed} value The text from which to strip tags
	     * @return {String} The stripped text
	     */
	    stripTags : function(v) {
	        return !v ? v : String(v).replace(stripTagsRE, "");
	    },
	
	    /**
	     * Strips all script tags
	     * @param {Mixed} value The text from which to strip script tags
	     * @return {String} The stripped text
	     */
	    stripScripts : function(v) {
	        return !v ? v : String(v).replace(stripScriptsRe, "");
	    },
	
	    /**
	     * Simple format for a file size (xxx bytes, xxx KB, xxx MB)
	     */
	    fileSize : function(size) {
	        if (size < 1024) {
	            return size + " bytes";
	        } else if (size < 1048576) {
	            return (Math.round(((size*10) / 1024))/10) + " KB";
	        } else {
	            return (Math.round(((size*10) / 1048576))/10) + " MB";
	        }
	    },
	
	    /**
	     * It does simple math for use in a template, for example:<pre><code>
	     * var tpl = new Ctj.Template('{value} * 10 = {value:math("* 10")}');
	     * </code></pre>
	     * @return {Function} A function that operates on the passed value.
	     */
	    math : function(){
	        var fns = {};
	        
	        return function(v, a){
	            if (!fns[a]) {
	                fns[a] = new Function('v', 'return v ' + a + ';');
	            }
	            return fns[a](v);
	        };
	    }(),
	
	    /**
	     * Rounds the passed number to the required decimal precision.
	     * @param {Number/String} value The numeric value to round.
	     * @param {Number} precision The number of decimal places to which to round the first parameter's value.
	     * @return {Number} The rounded value.
	     */
	    round : function(value, precision) {
	        var result = Number(value);
	        if (typeof precision == 'number') {
	            precision = Math.pow(10, precision);
	            result = Math.round(value * precision) / precision;
	        }
	        return result;
	    },
	
	    /**
	     * Formats the number according to the format string.
	     * <div style="margin-left:40px">examples (123456.789):
	     * <div style="margin-left:10px">
	     * 0 - (123456) show only digits, no precision<br>
	     * 0.00 - (123456.78) show only digits, 2 precision<br>
	     * 0.0000 - (123456.7890) show only digits, 4 precision<br>
	     * 0,000 - (123,456) show comma and digits, no precision<br>
	     * 0,000.00 - (123,456.78) show comma and digits, 2 precision<br>
	     * 0,0.00 - (123,456.78) shortcut method, show comma and digits, 2 precision<br>
	     * To reverse the grouping (,) and decimal (.) for international numbers, add /i to the end.
	     * For example: 0.000,00/i
	     * </div></div>
	     * @param {Number} v The number to format.
	     * @param {String} format The way you would like to format this text.
	     * @return {String} The formatted number.
	     */
	    number: function(v, format) {
	        if (!format) {
	            return v;
	        }
	       // v = Ext.num(v, NaN);
	        if (isNaN(v)) {
	            return '';
	        }
	        var comma = ',',
	            dec   = '.',
	            i18n  = false,
	            neg   = v < 0;
	
	        v = Math.abs(v);
	        if (format.substr(format.length - 2) == '/i') {
	            format = format.substr(0, format.length - 2);
	            i18n   = true;
	            comma  = '.';
	            dec    = ',';
	        }
	
	        var hasComma = format.indexOf(comma) != -1,
	            psplit   = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
	
	        if (1 < psplit.length) {
	            v = v.toFixed(psplit[1].length);
	        } else if(2 < psplit.length) {
	            throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
	        } else {
	            v = v.toFixed(0);
	        }
	
	        var fnum = v.toString();
	
	        psplit = fnum.split('.');
	
	        if (hasComma) {
	            var cnum = psplit[0], 
	                parr = [], 
	                j    = cnum.length, 
	                m    = Math.floor(j / 3),
	                n    = cnum.length % 3 || 3,
	                i;
	
	            for (i = 0; i < j; i += n) {
	                if (i != 0) {
	                    n = 3;
	                }
	                
	                parr[parr.length] = cnum.substr(i, n);
	                m -= 1;
	            }
	            fnum = parr.join(comma);
	            if (psplit[1]) {
	                fnum += dec + psplit[1];
	            }
	        } else {
	            if (psplit[1]) {
	                fnum = psplit[0] + dec + psplit[1];
	            }
	        }
	
	        return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
	    },
	
	    /**
	     * Returns a number rendering function that can be reused to apply a number format multiple times efficiently
	     * @param {String} format Any valid number format string for {@link #number}
	     * @return {Function} The number formatting function
	     */
	    numberRenderer : function(format) {
	        return function(v) {
	            return Ctj.Format.number(v, format);
	        };
	    },
	
	    /**
	     * Selectively do a plural form of a word based on a numeric value. For example, in a template,
	     * {commentCount:plural("Comment")}  would result in "1 Comment" if commentCount was 1 or would be "x Comments"
	     * if the value is 0 or greater than 1.
	     * @param {Number} value The value to compare against
	     * @param {String} singular The singular form of the word
	     * @param {String} plural (optional) The plural form of the word (defaults to the singular with an "s")
	     */
	    plural : function(v, s, p) {
	        return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
	    },
	
	    /**
	     * Converts newline characters to the HTML tag &lt;br/>
	     * @param {String} The string value to format.
	     * @return {String} The string with embedded &lt;br/> tags in place of newlines.
	     */
	    nl2br : function(v) {
	        return Ctj.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
	    },
	    join:function(sary,split){
	    	split = split||",";
			if(Ctj.isArray(sary)){
				return sary.join(split);
			}
			return sary||"";
		},
		stamp:function(tstamp,fmt){
			fmt = fmt||"yyyy-MM-dd hh:mm:ss";
			var d = new Date(tstamp);
			return this.date(d,fmt);
		},
	    tpl : function(tpl,data,scope){
	    	if(!tpl||!data){
	    		return;
	    	}
	    	var re =  /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g;
	    	
	    	var me =scope||this,fm = this,ret;
			function fn(m, name, format, args) {
	            if (format ) {
	                if (args) {
	                    args = [data[name]].concat(new Function('return ['+ args +'];')());
	                } else {
	                    args = [data[name]];
	                }
	                if (format.substr(0, 5) == "this.") {
	                    return me[format.substr(5)].apply(me, args);
	                }else {
	                    return fm[format].apply(fm, args);
	                }
	            }
	            else {
	                return data[name] !== undefined ? data[name] : "";
	            }
	        }
	        ret = tpl.replace(re, fn);
	        return ret;
	    }
	};
}();/*
    json2.js
    2015-05-03

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html


    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.


    This file creates a global JSON object containing two methods: stringify
    and parse. This file is provides the ES5 JSON capability to ES3 systems.
    If a project might run on IE8 or earlier, then this file should be included.
    This file does nothing on ES5 systems.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the value

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 
                            ? '0' + n 
                            : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date 
                    ? 'Date(' + this[key] + ')' 
                    : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint 
    eval, for, this 
*/

/*property
    JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== 'object') {
    JSON = {};
}

(function () {
    'use strict';
    
    var rx_one = /^[\],:{}\s]*$/,
        rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
        rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
        rx_four = /(?:^|:|,)(?:\s*\[)+/g,
        rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 
            ? '0' + n 
            : n;
    }
    
    function this_value() {
        return this.valueOf();
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function () {

            return isFinite(this.valueOf())
                ? this.getUTCFullYear() + '-' +
                        f(this.getUTCMonth() + 1) + '-' +
                        f(this.getUTCDate()) + 'T' +
                        f(this.getUTCHours()) + ':' +
                        f(this.getUTCMinutes()) + ':' +
                        f(this.getUTCSeconds()) + 'Z'
                : null;
        };

        Boolean.prototype.toJSON = this_value;
        Number.prototype.toJSON = this_value;
        String.prototype.toJSON = this_value;
    }

    var gap,
        indent,
        meta,
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        rx_escapable.lastIndex = 0;
        return rx_escapable.test(string) 
            ? '"' + string.replace(rx_escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string'
                    ? c
                    : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' 
            : '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) 
                ? String(value) 
                : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0
                    ? '[]'
                    : gap
                        ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
                        : '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === 'string') {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (
                                gap 
                                    ? ': ' 
                                    : ':'
                            ) + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (
                                gap 
                                    ? ': ' 
                                    : ':'
                            ) + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0
                ? '{}'
                : gap
                    ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
                    : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        };
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            rx_dangerous.lastIndex = 0;
            if (rx_dangerous.test(text)) {
                text = text.replace(rx_dangerous, function (a) {
                    return '\\u' +
                            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (
                rx_one.test(
                    text
                        .replace(rx_two, '@')
                        .replace(rx_three, ']')
                        .replace(rx_four, '')
                )
            ) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function'
                    ? walk({'': j}, '')
                    : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
}());
Ctj.info=function(title,msg){
	Ctj.alert(title,msg);
};

Ctj.alert=function(title,msg){
	if(!msg){
		msg = title;
		title="提示";
	}
	alert(title+":"+msg);
};

Ctj.warn=function(title,msg){
	if(!msg){
		msg = title;
		title="警告";
	}
	alert(title+":"+msg);
};

Ctj.error=function(title,msg){
	if(!msg){
		msg = title;
		title="错误";
	}
	alert(title+":"+msg);
};

Ctj.confirm=function(title,msg,fn){
	if(!fn&&Ctj.isFunction(msg)){
		fn=msg;
		msg = title;
		title="提示";
	}
	var b = confirm(title+":"+msg);
	if(Ctj.isFunction(b)){
		fn(b);
	}
};

Ctj.showMask=function(){
	return $('<div class="ctj_mask" style="opacity: 0.5; position: fixed; z-index: 9999; top: 0px; left: 0px; width: 100%; height: 100%; background: rgb(218, 212, 212);"></div>').appendTo('body');
};

Ctj.closeMask=function($mask){
	if($mask){
		$mask.remove();
	}else{
		$("div.ctj_mask").remove();
	}
};

Ctj.showProgress=function(options){
	var htmlAry=[
	    '<div class="ctj_progress" style="opacity: 0.2; position: fixed; z-index: 9999; top: 0px; left: 0px; width: 100%; height: 100%; background: rgb(218, 212, 212);">',
	    '<div style="width:200px;margin:200px auto;padding:36px;border:1px solid black;text-align:center;">'+((options&&options.msg)?options.msg:'正在请求中...')+'</div>',         
	    '</div>'];
	return $(htmlAry.join("")).appendTo('body');
};

Ctj.closeProgress=function($progress){
	if($progress){
		$progress.remove();
	}else{
		$("div.ctj_progress").remove();
	}
};
Ctj.Util={
	/**
	 * 函数拦截器
	 */
	createInterceptor:function(fn,before,after,returnValue){
		return function(){
			var me =this,args = arguments,f=fn;
			if($.isFunction(before)){
				if(before.apply(me,args)===false){
					return;
				}
			}
			var value = f.apply(me,args);
			if($.isFunction(after)){
				var nArgs;
				if(returnValue===true){
					nArgs=Array.prototype.slice.call(args,0,args.length);
					nArgs.push(value);
				}
				value = after.apply(me,nArgs||args)
			}
			if(returnValue===true){
				return value;
			}
		}
	},
	/**
	 * hash值
	 */
	hash:function(str,caseSensitive){
		if(!caseSensitive){
	        str = str.toLowerCase();
	    }
	    var hash  =   1315423911,i,ch;
	    for (i = str.length - 1; i >= 0; i--) {
	        ch = str.charCodeAt(i);
	        hash ^= ((hash << 5) + ch + (hash >> 2));
	    }
	    return  (hash & 0x7FFFFFFF);

	},
	/**
	 * 获取浏览器地址栏参数
	 * 
	 */
	getPageAllParams:function(){
		var str = window.location.search.substr(1);
		var params ={};
		if(str){
			var pAry = str.split("&");
			for(var i=0;i<pAry.length;i++){
				var pStr = pAry[i];
				var tempIndex = pStr.indexOf("=");
				var key = decodeURI(pStr.substring(0,tempIndex));
				var value = decodeURI(pStr.substring(tempIndex+1));
				params[key] = value;
			}
		}
		return params;
	},
	/**
	 * 根据name获取浏览器地址栏参数
	 */
	getPageParam:function(name){
		var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); 
		var r = window.location.search.substr(1).match(reg);  
		if (r!=null){
			return decodeURI((r[2])); 
		}
		return null;
	},
	createUrlParamStr:function(url,params){
		if(!params){
			params=url;
			url="";
		}
		var sParam="";
		for(var key in params){
			sParam+=decodeURI(key)+"="+decodeURI(params[key])+"&";
		}
		if(url.indexOf("?")>0){
			url = url+"&"+sParam;
		}else{
			url = url+"?"+sParam;
		}
		return url;
	}
};
Ctj.apply(Ctj,Ctj.Util);





